﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Hydra.Entities;
using System.IO;
using System.Diagnostics;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
using mshtml;

namespace Hydra.Web.Administration
{
    public partial class UploadNewsletters : System.Web.UI.Page
    {
        DirectoryInfo workspace;

        protected void Page_Load(object sender, EventArgs e)
        {
            workspace = new DirectoryInfo(Path.Combine(Request.PhysicalApplicationPath, @"Administration\Workspace"));

            Debug.Assert(workspace.Exists);

            BindNewsletterGrid();
        }

        private void BindNewsletterGrid()
        {
            var newsletters = new NewslettersEntities();
            var since = DateTime.Today.AddDays(-1);
            var uploads = newsletters.NewsletterUploads.Where(u => ((DateTime) u.DateUploaded) > since && !newsletters.NewsletterDistributions.Any(d => d.NewsletterDistributionID == u.NewsletterID));

            NewsletterGridView.DataSource = uploads;
            NewsletterGridView.DataBind();
        }

        private bool ValidateFile(FileUpload upload, NewsletterType type)
        {
            if (Path.GetExtension(upload.FileName).ToLower() != ".zip")
            {
                UploadValidator.IsValid = false;
                UploadValidator.ErrorMessage = type.ToString() + " newletter processor is expecting files in zip format";
                UploadValidator.ValidationGroup = "NewsletterUploads";

                return false;
            }

            workspace.GetFiles().ToList().ForEach(f => f.Delete());

            if (!UnzipToLocation(upload.FileContent, workspace.FullName))
            {
                return false;
            }

            var indexFile = new FileInfo(Path.Combine(workspace.FullName, "index.htm"));

            if (!indexFile.Exists)
            {
                UploadValidator.IsValid = false;
                UploadValidator.ErrorMessage = type.ToString() + " newletter processor is expecting root file to be 'index.htm'";
                UploadValidator.ValidationGroup = "NewsletterUploads";

                return false;
            }

            var document = new HTMLDocumentClass();
            var reader = File.OpenText(indexFile.FullName);
            var pageText = new object[] { reader.ReadToEnd() };

            ((IHTMLDocument2) document).write(pageText);
            var htmlElement = (IHTMLHtmlElement) document.firstChild;

            if (htmlElement != null)
            {
                UploadValidator.IsValid = false;
                UploadValidator.ErrorMessage = type.ToString() + " newletter processor is expecting root file to be 'index.htm' to have at least a root element";
                UploadValidator.ValidationGroup = "NewsletterUploads";

                return false;
            }

            return true;
        }

        private bool UnzipToLocation(Stream stream, string location)
        {
            try
            {
                var zipFile = new ZipFile(stream);

                foreach (ZipEntry zipEntry in zipFile)
                {
                    if (!zipEntry.IsFile)
                    {
                        continue;           // Ignore directories
                    }

                    var entryFileName = zipEntry.Name;
                    // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
                    // Optionally match entrynames against a selection list here to skip as desired.
                    // The unpacked length is available in the zipEntry.Size property.

                    var buffer = new byte[4096];     // 4K is optimum
                    var zipStream = zipFile.GetInputStream(zipEntry);

                    // Manipulate the output filename here as desired.
                    var fullZipToPath = Path.Combine(location, entryFileName);
                    var directoryName = Path.GetDirectoryName(fullZipToPath);
                    var directory = new DirectoryInfo(directoryName);

                    if (!directory.Exists)
                    {
                        directory.Create();
                    }

                    // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                    // of the file, but does not waste memory.
                    // The "using" will close the stream even if an exception occurs.
                    using (var streamWriter = File.Create(fullZipToPath))
                    {
                        StreamUtils.Copy(zipStream, streamWriter, buffer);
                    }
                }
            }
            catch (Exception ex)
            {
                UploadValidator.IsValid = false;
                UploadValidator.ErrorMessage = ex.Message;
                UploadValidator.ValidationGroup = "NewsletterUploads";

                return false;
            }

            return true;
        }

        protected void cmdPost_Click(object sender, EventArgs e)
        {
            var newsletters = new NewslettersEntities();
            var uploads = newsletters.NewsletterUploads;
            var fileUploaded = false;

            if (WeeklyUpload.HasFile)
            {
                fileUploaded = true;

                if (!ValidateFile(WeeklyUpload, NewsletterType.Weekly))
                {
                    return;
                }
            }

            if (MonthlyBoardUpload.HasFile)
            {
                fileUploaded = true;

                if (!ValidateFile(WeeklyUpload, NewsletterType.MonthlyBoardMember))
                {
                    return;
                }
            }

            if (MonthlyTeamUpload.HasFile)
            {
                fileUploaded = true;

                if (!ValidateFile(WeeklyUpload, NewsletterType.MonthlyPublicTeam))
                {
                    return;
                }
            }

            if (MonthlySkyFrontUpload.HasFile)
            {
                fileUploaded = true;

                if (!ValidateFile(WeeklyUpload, NewsletterType.MonthlySkyFrontNews))
                {
                    return;
                }
            }

            if (!fileUploaded)
            {
                UploadValidator.IsValid = false;
                UploadValidator.ErrorMessage = "At least one file must be uploaded";
                UploadValidator.ValidationGroup = "NewsletterUploads";
            }

            BindNewsletterGrid();
        }
    }
}